/*-
 * Copyright (C) 2018-2020, Shanghai Trusted Industry Control Platform Co., Ltd.
 * Created by 周正辉 (Zhenghui Zhou) <zhouzhenghui@ticpsh.com>, 赵楷文 (Kaiwen
 * Zhao) <zhaokaiwen@ticpsh.com>
 */

#ifndef COMMON_CORDER_H
#define COMMON_CORDER_H

#include <clang/AST/AST.h>
#include <clang/AST/Mangle.h>
#include <clang/Basic/ABI.h>
#include <clang/Lex/Lexer.h>
#include <llvm/Support/raw_os_ostream.h>

#include <nlohmann/json.hpp>
#include <string>

#include "AttrAnalyzer.h"

namespace rocket {
namespace common {

/**
 * @brief 构建显示策略
 */
clang::PrintingPolicy createPrintingPolicy(const clang::LangOptions &lo);
clang::PrintingPolicy createPrintingPolicy(const clang::ASTContext &ast);

/**
 * @brief 获取有名声明的带边界可用全名或修饰名。
 * 不修饰时，输出的名将会包含说有边界名，形如"SCOPE::NAME"。
 * 修饰时，输出clang编译器内部mangled name
 */
std::string getFullNDeclName(const clang::NamedDecl *nd, bool mangled = false);

/**
 * @brief 获取各种格式的函数名
 */
std::string getFullFuncName(const clang::FunctionDecl *fd, bool with_scope,
                            bool with_parms);

/**
 * @brief 获取类型的带边界可用全名。
 */
std::string getFullQTypeName(const clang::QualType &qt,
                             const clang::ASTContext &ast);

/**
 * @brief 获取有名声明的名的完整边界前缀名
 */
void getFullScopeStr(const clang::NamedDecl *ND, llvm::raw_ostream &OS,
                     const clang::PrintingPolicy &P);
std::string getFullScopeStr(const clang::NamedDecl *ND);

/**
 * @brief 使用clang的方法显示完整的声明字符串
 */
std::string getFullDeclStr(const clang::Decl *decl);

/**
 * @brief 使用clang的方法显示完整的语句字符串
 */
std::string getFullStmtStr(const clang::Stmt *decl,
                           const clang::ASTContext &ast);

/**
 * @brief 使用clang的方法显示模板实参的名字符串
 */
std::string getFullSpecArgStr(const clang::TemplateArgument &ta,
                              const clang::ASTContext &ast);

/**
 * @brief 获取包含"<>"的模板实参列表
 */
std::string getFullTempSpecArgsList(
    clang::ArrayRef<clang::TemplateArgument> Args,
    const clang::PrintingPolicy &Policy);

/**
 * @brief 获取包含"<>"的模板实参列表
 */
std::string getFullTempSpecArgsList(const clang::FunctionDecl *fd);

/**
 * @brief 获取包含"<>"的模板实参列表
 */
std::string getFullTempSpecArgsList(const clang::CXXRecordDecl *cxxrd);

/**
 * @brief 获取包含"<>"的以模板形参形式特化的模板列表
 */
std::string getFullTempParamsSpecList(
    const clang::TemplateParameterList &Params,
    const clang::PrintingPolicy &Policy);

/**
 * @brief 得到重载的操作符名
 */
std::string getOverloadedOperatorName(clang::OverloadedOperatorKind ook);

/**
 * @brief 构建给定类型的声明语句
 */
std::string makeVarDecl(const std::string &type_str,
                        const std::string &var_name);
std::string makeVarDecl(const clang::QualType &type, std::string var_name,
                        const clang::ASTContext &ast, bool allow_suger = false,
                        bool is_top = true);
std::string makeFuncPtrDecl(const clang::FunctionType *func_type,
                            const std::string &fptr_name,
                            const clang::ASTContext &ast);
std::string makeFuncPtrDecl(const clang::FunctionDecl *func,
                            const std::string &fptr_name,
                            const clang::ASTContext &ast);

/**
 * @brief 构建模板形参列表
 * @param parm_list
 * @return
 */
std::string makeTemplateParmList(const clang::TemplateParameterList *parm_list);

/**
 * @brief 根据给出的函数类型，仿制一个函数声明
 */
std::string makeFuncTypeCopy(
    const clang::FunctionType *func_type, std::string fname,
    const clang::ASTContext &ast,
    const std::map<size_t, std::string> &param_names = {});

/**
 * @brief makeFuncDeclCopy 可设置的函数声明仿制
 * @param func_decl 仿制声明原型
 * @param fname 替换的函数名
 * @param param_names 形参名
 * @param require_params_name_force 形参名填充
 * @param require_template_params 模板形参列表补充
 * @param require_scope 声明边界补充
 * @return 仿制的声明字符串
 */
std::string makeFuncDeclCopy(const clang::FunctionDecl *func_decl,
                             const std::string &fname,
                             // -------------
                             // params info
                             const std::map<size_t, std::string> &param_names,
                             bool require_params_name_force,
                             bool require_params_init,
                             // -------------
                             // first decl flag
                             bool is_first_decl);

std::string makeFuncFstDeclCopy(
    const clang::FunctionDecl *func_decl, std::string fname,
    const std::map<size_t, std::string> &param_names = {});
std::string makeFuncDefDeclCopy(
    const clang::FunctionDecl *func_decl, std::string fname,
    const std::map<size_t, std::string> &param_names = {});
std::string makeFuncOriDeclCopy(const clang::FunctionDecl *func_decl);

void removeNullValues(nlohmann::json &j);
}  // namespace common
}  // namespace rocket

#endif
